package cn.enited.devtools.apiaggregator.service.impl;

import cn.enited.devtools.apiaggregator.api.analysis.ApiAnalyzer;
import cn.enited.devtools.apiaggregator.api.cache.ApiCacheManager;
import cn.enited.devtools.apiaggregator.api.invoke.ApiInvoker;
import cn.enited.devtools.apiaggregator.api.vo.ApiAnalysisObject;
import cn.enited.devtools.apiaggregator.consts.CommonConst;
import cn.enited.devtools.apiaggregator.consts.ErrorCode;
import cn.enited.devtools.apiaggregator.entity.ApiAggObject;
import cn.enited.devtools.apiaggregator.entity.Project;
import cn.enited.devtools.apiaggregator.exception.BizException;
import cn.enited.devtools.apiaggregator.service.ApiConfService;
import cn.enited.devtools.apiaggregator.service.ApiGoService;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class ApiGoServiceImpl implements ApiGoService {

    private ApiConfService confService;

    private ApiCacheManager cacheManager;

    private ApiAnalyzer analyzer;

    private ApiInvoker invoker;

    @Autowired
    public void setConfService(ApiConfService confService) {
        this.confService = confService;
    }

    @Autowired
    public void setCacheManager(ApiCacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Autowired
    public void setAnalyzer(ApiAnalyzer analyzer) {
        this.analyzer = analyzer;
    }

    @Autowired
    public void setInvoker(ApiInvoker invoker) {
        this.invoker = invoker;
    }

    @Override
    public Map<String, Object> execute(String projectName, String environment, String apiName,
                                       HttpServletRequest apiRequest, String bodyJson) {
        if (!StrUtil.containsAny(environment, CommonConst.API_ENV.PRODUCT, CommonConst.API_ENV.TEST, CommonConst.API_ENV.TRAINING)) {
            log.error(StrUtil.format("ApiGoService -> 无效的运行环境标识：", environment));
            throw new BizException(ErrorCode.ERROR.code(), "运行环境配置时出错");
        }
        ApiAnalysisObject analysisObject = cacheManager.getAnalysisObject(projectName, apiName);
        if (Objects.isNull(analysisObject)) {
            ApiAggObject primitiveObject = confService.getEntityByName(projectName, apiName);
            try {
                analysisObject = analyzer.analyse(primitiveObject);
                cacheManager.putAnalysisObject(projectName, apiName, analysisObject);
            } catch (Exception e) {
                log.error("ApiGoService -> 未能从缓存中找到分析对象，从数据库加载进行分析时发生异常：", e);
                throw new BizException(ErrorCode.ERROR.code(), "调用服务配置时出错");
            }
        }
        Project.Configuration pathConf = cacheManager.getProjectPath(projectName, environment);
        if (Objects.isNull(pathConf)) {
            log.error(StrUtil.format("ApiGoService -> 服务路径配置为空：没有为运行环境[{}]配置服务路径", environment));
            throw new BizException(ErrorCode.ERROR.code(), "服务路径配置时出错");
        }
        return invoker.invokeService(pathConf, analysisObject, apiRequest, bodyJson);
    }
}
